package com.smartwebx.ha.dal.util.core;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.smartwebx.ha.dal.usebean.DateValue;
import com.smartwebx.ha.dal.usebean.FeatureRainfallYear;
import com.smartwebx.ha.dal.usebean.RainSlideDay;
import com.smartwebx.ha.dal.usebean.RainSlideHour;
import com.smartwebx.ha.dal.usebean.abstr.AbstractValue;
import com.smartwebx.ha.dal.usebean.enu.FeatureRainfallEnum;
import com.smartwebx.ha.dal.util.DateValueHandler;

/**
 * （面）雨量滑动分析
 * 
 * @author XX
 * 
 */
public class RainSlideAnalysis {
	/**
	 * 日滑动分析
	 * 
	 * @param featureRainfallYears
	 *            历史数据
	 * @param realTimeRainfallDay
	 *            实时数据
	 * @return
	 */
	public static RainSlideDay getSlideAnalysisDay(
			List<FeatureRainfallYear> featureRainfallYears,
			List<DateValue> realTimeRainfallDay) {
		RainSlideDay rainSlideD = new RainSlideDay();

		// 1、3、7、15、30 日数据
		Integer[] slideDays = { 1, 3, 7, 15, 30 };
		Map<Integer, String> slideDayMethodKey = ImmutableMap.of(1, "One", 3,
				"Three", 7, "Seven", 15, "Fifteen", 30, "Thirty");
		// 计算实时数据比较 并与历史数据比较，得到排位、排序后的数据
		for (Integer slideDay : slideDays) {
			DateValue realTimeData = getSlideNumMaxData(realTimeRainfallDay,
					slideDay);
			FeatureRainfallEnum featureRainfallEnum = EnumUtils.getEnum(
					FeatureRainfallEnum.class, "D" + slideDay);
			Entry<List<Integer>, List<DateValue>> sortIndexDataOrder = realHistDataCompare(
					realTimeData, featureRainfallYears, featureRainfallEnum);

			String methodKey = slideDayMethodKey.get(slideDay);
			try {
				MethodUtils.invokeMethod(rainSlideD, "set" + methodKey,
						realTimeData);
				// 设置排名
				MethodUtils.invokeMethod(rainSlideD, "set" + methodKey
						+ "SotrHistory", sortIndexDataOrder.getKey());
				// 设置序列
				MethodUtils.invokeMethod(rainSlideD, "set" + methodKey
						+ "ViewDates", sortIndexDataOrder.getValue());
			} catch (NoSuchMethodException | IllegalAccessException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		return rainSlideD;
	}

	/**
	 * 小时滑动分析
	 * 
	 * @param featureRainfallYears
	 *            历史数据
	 * @param realTimeRainfallHour
	 *            实时数据
	 * @return
	 */
	public static RainSlideHour getSlideAnalysisHour(
			List<FeatureRainfallYear> featureRainfallYears,
			List<DateValue> realTimeRainfallHour) {
		RainSlideHour rainSlideHour = new RainSlideHour();

		// 1、3、6、12、24 小时数据
		Integer[] slideDays = { 1, 3, 6, 12, 24 };
		Map<Integer, String> slideDayMethodKey = ImmutableMap.of(1, "OneHour",
				3, "ThreeHour", 6, "SixHour", 12, "TwelveHour", 24,
				"TwentyFourHour");
		// 计算实时数据比较 并与历史数据比较，得到排位、排序后的数据
		for (Integer slideDay : slideDays) {
			DateValue realTimeData = getSlideNumMaxData(realTimeRainfallHour,
					slideDay);
			FeatureRainfallEnum featureRainfallEnum = EnumUtils.getEnum(
					FeatureRainfallEnum.class, "H" + slideDay);
			Entry<List<Integer>, List<DateValue>> sortIndexDataOrder = realHistDataCompare(
					realTimeData, featureRainfallYears, featureRainfallEnum);

			String methodKey = slideDayMethodKey.get(slideDay);
			try {
				MethodUtils.invokeMethod(rainSlideHour, "set" + methodKey,
						realTimeData);
				// 设置排名
				MethodUtils.invokeMethod(rainSlideHour, "set" + methodKey
						+ "SotrHistory", sortIndexDataOrder.getKey());
				// 设置序列
				MethodUtils.invokeMethod(rainSlideHour, "set" + methodKey
						+ "ViewDates", sortIndexDataOrder.getValue());
			} catch (NoSuchMethodException | IllegalAccessException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		return rainSlideHour;
	}

	/**
	 * 获得不同滑动日的最大数据
	 * 
	 * @param realTimeData
	 * @param slideNum
	 * @return
	 */
	private static DateValue getSlideNumMaxData(List<DateValue> realTimeData,
			Integer slideNum) {
		if (realTimeData.isEmpty()) {
			return DateValue.getDefDv();
		}

		int sizeNum = realTimeData.size();
		List<List<DateValue>> result = Lists.newArrayList();
		if (sizeNum < slideNum) {
			result.add(realTimeData);
		} else {
			int endNum = slideNum;
			int starNum = 0;
			for (;;) {
				if (endNum - 1 == sizeNum)
					break;
				result.add(realTimeData.subList(starNum++, endNum++));
			}
		}

		List<Double> valArr = Lists.newArrayList();
		for (List<DateValue> dvs : result) {
			valArr.add(DateValueHandler.sumByObj(dvs));
		}
		Double maxVal = Ordering.natural().max(valArr);
		int maxIndex = valArr.indexOf(maxVal);
		List<DateValue> maxColl = result.get(maxIndex);
		DateValue newFindDv = new DateValue();
		if (!maxColl.isEmpty()) {
			DateValue findDv = maxColl.get(0);
			newFindDv.setTm(findDv.getTm());
			newFindDv.setVal(maxVal);
		}

		return newFindDv;
	}

	private static Entry<List<Integer>, List<DateValue>> realHistDataCompare(
			DateValue realTimeData,
			List<FeatureRainfallYear> featureRainfallYears,
			final FeatureRainfallEnum featureRainfallEnum) {
		List<DateValue> realHistDatas = Lists.newArrayList();

		if (realTimeData.getTm() != null) {
			realHistDatas.add(realTimeData);
		}
		// 过滤符合滑动日的数据
		Iterable<FeatureRainfallYear> filterRainValBySlide = Iterables.filter(
				featureRainfallYears, new Predicate<FeatureRainfallYear>() {
					@Override
					public boolean apply(FeatureRainfallYear input) {
						return StringUtils.equalsIgnoreCase(input.getPrd(),
								featureRainfallEnum.toString());
					}
				});
		for (FeatureRainfallYear featureRainfall : filterRainValBySlide) {
			DateValue featureDv = new DateValue();
			featureDv.setTm(featureRainfall.getMxtm());
			featureDv.setVal(featureRainfall.getMxp());
			realHistDatas.add(featureDv);
		}
		Ordering<AbstractValue> valOrder = DateValueHandler.byValueOrder();
		// 降序
		Collections.sort(realHistDatas, valOrder.reverse());
		// 排位
		int realTimeIndex = realHistDatas.indexOf(realTimeData);

		List<Integer> realHistorySort = Lists.newArrayList(++realTimeIndex,
				realHistDatas.size());

		return Maps.immutableEntry(realHistorySort, realHistDatas);
	}
}
